"""
FaceBook客户端 - 简化版本
整合了浏览器操作、数据采集、服务管理等功能
"""
import asyncio
from re import T
import traceback
import uuid
import os
import re
from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta
from playwright.async_api import async_playwright, Browser, BrowserContext, Page
from pydantic import BaseModel, Field
from sqlalchemy.engine.cursor import ResultFetchStrategy
from core.utils.logger_manager import LoggerManager
from core.chrome_manager import get_chrome_manager
from core.utils.chrome_finder import ChromeFinder
from config.settings import settings
import random, asyncio
from database.connection import db_manager
from database.repositories import GroupInfoRepository, UserProfileRepository, CommentRepository, MessageRepository
from core.agent import CustomerAnalyzer
from core.cookies_manager import CookiesManager
class FaceBookProfile(BaseModel):
    """FaceBook用户档案模型"""
    profile_id: str = Field(None, description="FaceBook用户ID")
    name: Optional[str] = Field(None, description="用户名/昵称")
    title: Optional[str] = Field(None, description="职位")
    headline: Optional[str] = Field(None, description="个人简介/标题")
    profile_url: Optional[str] = Field(None, description="个人主页链接")
    avatar_url: Optional[str] = Field(None, description="头像链接")
    company: Optional[str] = Field(None, description="公司")
    industry: Optional[str] = Field(None, description="行业")
    experience: Optional[Any] = Field(None, description="工作经历")
    education: Optional[Any] = Field(None, description="教育背景")
    skills: Optional[Any] = Field(None, description="技能")
    summary: Optional[str] = Field(None, description="个人总结")
    phone: Optional[Any] = Field(None, description="电话")
    website: Optional[Any] = Field(None, description="网站")
    address: Optional[Any] = Field(None, description="地址")
    email: Optional[str] = Field(None, description="邮箱")
    platform: Optional[str] = Field("FaceBook", description="平台")


class FaceBookSearchParams(BaseModel):
    """FaceBook搜索参数"""
    keyword: str = Field(..., description="搜索关键词")
    location: Optional[str] = Field(None, description="位置")
    max_pages: int = Field(1, description="最大页数")
    results_per_page: int = Field(10, description="每页结果数")


class FaceBookClient:
    """FaceBook客户端 - 整合所有功能"""
    
    def __init__(self, debug_port: int = 9222,cookie:List[Dict[str, Any]]=None,task_id:str=None):
        self.logger = LoggerManager.get_task_logger("FaceBook",task_id)
       
        self.chrome_manager = get_chrome_manager()
        self.browser: Optional[Browser] = None
        self.context: Optional[BrowserContext] = None
        self.page: Optional[Page] = None
        self.is_logged_in = False
        self.cookie=cookie
        self.current_browser_id: Optional[str] = None
        self.debug_port=debug_port
        self.cookies_manager = CookiesManager()
        self.task_id=task_id
        # 初始化AI客户分析器
        self.customer_analyzer = CustomerAnalyzer()
        self.account =''
    
    def parse_time_text(self, time_text: str) -> str:
        """
        解析时间文本，将相对时间转换为绝对时间格式
        如: 1d -> 2025-09-16 14:00:00, 1h -> 2025-09-17 13:00:00
        其他格式保持原样，但会过滤掉非时间文本
        """
        if not time_text:
            return ""
            
        # 过滤掉明显不是时间的文本
        non_time_keywords = ['reply', 'like', 'share', 'comment', 'more', 'translate', 'see more', 'hide']
        if time_text.strip().lower() in non_time_keywords:
            return ""
            
        # 当前时间
        now = datetime.now()
        
        # 匹配相对时间格式 (1d, 2h, 3m, 等)
        pattern = r'^(\d+)([dhmy])$'
        match = re.match(pattern, time_text.strip().lower())
        
        if match:
            value = int(match.group(1))
            unit = match.group(2)
            
            if unit == 'd':
                # 减去天数
                target_time = now - timedelta(days=value)
            elif unit == 'h':
                # 减去小时数
                target_time = now - timedelta(hours=value)
            elif unit == 'm':
                # 减去分钟数
                target_time = now - timedelta(minutes=value)
            elif unit == 'w':
                # 减去星期数
                target_time = now - timedelta(weeks=value)
            elif unit == 'y':
                # 减去年数 (近似为365天)
                target_time = now - timedelta(days=value*365)
            else:
                # 未知单位，返回原文本
                return time_text
                
            # 格式化为 YYYY-MM-DD HH:MM:SS
            return target_time.strftime("%Y-%m-%d %H:%M:%S")
        
        # 如果不匹配相对时间格式，返回原文本
        return time_text
        
    async def start_browser(self, headless: bool = False, proxy_config: Dict[str, str] = None) -> bool:
        """启动浏览器 - 使用新的浏览器管理逻辑"""
        try:
            
            # 连接浏览器
            playwright = await async_playwright().start()
          
            self.browser = await playwright.chromium.connect_over_cdp(f"http://localhost:{self.debug_port}")
            
            # 获取浏览器上下文和页面
            if self.browser.contexts:
                self.context = self.browser.contexts[0]
                if self.cookie:
                    await self.context.add_cookies(self.cookie)
                if self.context.pages:
                    self.page = self.context.pages[0]
                    self.logger.info("使用现有的page")
                else:
                    self.page = await self.context.new_page()
                    self.logger.info("创建新的page")
            else:
                # 如果没有上下文，创建新的
                self.context = await self.browser.new_context(
                    viewport={'width': 1920, 'height': 1080},
                    user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
                )
                if self.cookie: 
                    await self.context.add_cookies(self.cookie)
                self.page = await self.context.new_page()
                self.logger.info("创建新的context和page")
            
            self.logger.info(f"FaceBook浏览器启动成功，浏览器ID: {self.current_browser_id}")
            return True
            
        except Exception as e:
            self.logger.error(f"启动浏览器失败: {str(e)}")
            return False
    
    async def close_browser(self):
        """关闭浏览器连接"""
        try:
            if self.page:
                await self.page.close()
            if self.context:
                await self.context.close()
            # CDP连接不需要关闭browser，只关闭Playwright连接
            self.logger.info("FaceBook浏览器连接已关闭")
        except Exception as e:
            self.logger.error(f"关闭浏览器连接失败: {str(e)}")
    
    async def login(self, wait_timeout: int = 600) -> bool:
        """等待用户手动登录FaceBook"""
        try:
            if not await self.start_browser():
                return False
            
            # 访问登录页面
            await self.page.goto("https://www.facebook.com/")
            await self.page.wait_for_load_state("domcontentloaded")
            
            self.logger.info("请在浏览器中手动登录FaceBook，等待登录成功...")
            
            # 等待用户登录成功，最长等待10分钟
            start_time = asyncio.get_event_loop().time()
            
            while True:
                try:
                    # 检查当前URL是否为目标页面
                    current_url = self.page.url
                    
                    # 检查页面上是否存在搜索输入框元素，判断是否登录成功
                    search_box = await self.page.query_selector('svg[aria-label="Your profile"]')
                    if search_box is not None:
                        self.is_logged_in = True
                        self.cookie=await self.context.cookies()
                        self.cookies_manager.save_cookies("facebook", self.cookie)
                        self.logger.info("FaceBook登录成功！")
                          # 从页面源码中提取账户名称
                        page_content = await self.page.content()
                        name_match = re.search(r'"NAME"\s*:\s*"([^"]+)"', page_content)
                        if name_match:
                            self.account = name_match.group(1)
                            self.logger.info(f"账户名称提取成功: {self.account}")
                        else:
                            self.logger.warning("未能从页面源码中提取账户名称")
                        return True
                    
                    # 检查是否超时
                    elapsed_time = asyncio.get_event_loop().time() - start_time
                    if elapsed_time > wait_timeout:
                        self.logger.error(f"登录超时，等待时间超过{wait_timeout}秒")
                        return False
                    
                    # 等待1秒后再次检查
                    await asyncio.sleep(1)
                    
                except Exception as e:
                    self.logger.warning(f"检查登录状态时出错: {str(e)}")
                    await asyncio.sleep(1)
                    continue
                
        except Exception as e:
            self.logger.error(f"FaceBook登录失败: {str(e)}")
            return False
    
    async def check_login_status(self, wait_timeout: int = 600) -> bool:
        """检查登录状态 - 循环检测直到登录成功或超时"""
        try:
            if not self.page:
                # 如果有多个pages，默认选择第一个
                if hasattr(self, 'context') and self.context:
                    pages = self.context.pages
                    if pages:
                        self.page = pages[0]
                       
                    else:
                        return False
                else:
                    return False
            
            self.logger.info("开始检测FaceBook登录状态...")
           
                    # 等待1秒后再次检测
            try:
                await self.page.goto("https://www.faceBook.com")
                await asyncio.sleep(3)
                # await self.page.wait_for_load_state("domcontentloaded", timeout=10000)  # 10秒超时
            except Exception:
                # 如果domcontentloaded超时，继续执行
                pass   
            # 等待用户登录成功，最长等待10分钟
            start_time = asyncio.get_event_loop().time()
            
            while True:
                try:
                              
                    # 检查当前URL是否为目标页面
               
                    
                    # 检查页面上是否存在svg元素，aria-label为"Your profile"，判断是否登录成功
                    search_box = await self.page.query_selector('svg[aria-label="Your profile"]')
                    if search_box is not None:
                       
                        self.is_logged_in = True
                        self.cookie=await self.context.cookies()
                        self.cookies_manager.save_cookies("facebook", self.cookie)
                        self.logger.info("FaceBook登录成功！")
                        page_content = await self.page.content()
                        name_match = re.search(r'"NAME"\s*:\s*"([^"]+)"', page_content)
                        if name_match:
                            self.account = name_match.group(1)
                            self.logger.info(f"账户名称提取成功: {self.account}")
                        else:
                            self.logger.warning("未能从页面源码中提取账户名称")
                        return True
                    
                    # 检查是否超时
                    elapsed_time = asyncio.get_event_loop().time() - start_time
                    if elapsed_time > wait_timeout:
                        self.logger.error(f"登录检测超时，等待时间超过{wait_timeout}秒")
                        self.is_logged_in = False
                        return False
                    
                   
                    
                except Exception as e:
                    self.logger.warning(f"检测登录状态时出错: {str(e)}")
                    if 'Target page, context or browser has been closed' in str(e):
                      await self.start_browser()
                    await asyncio.sleep(30)
                    continue
               
                await asyncio.sleep(1)
                    
        except Exception as e:
            self.logger.error(f"检查登录状态失败: {str(e)}")
            return False
    
    async def search_profiles(self, search_params: FaceBookSearchParams) -> List[FaceBookProfile]:
        """搜索用户档案"""
        try:
            self.logger.info(f"🕵️‍♂️ 采集facebook数据", extra={"show_in_ui": 1, "task_id": self.task_id})
            finnal_results={'people_or_company_info':[],'comment_people_info':[]}
            # 构建搜索URL
            search_url = f"https://www.facebook.com/search/top/?q={search_params.keyword}"
          
            
            # 访问搜索页面
          
            try:
                try:
                    await self.page.goto(search_url,timeout=30000)
                except Exception:
                    pass
                await asyncio.sleep(3)
                await self.page.wait_for_load_state("domcontentloaded", timeout=10000)  # 10秒超时
            except Exception:
                # 如果domcontentloaded超时，继续执行
                pass
            mixed_results=await self.extract_all_reels_and_story_comments()
            self.logger.info(f"提取评论用户，共{len(mixed_results['profile_users'])}条")
            pages_info = await self.extract_pages_info()
            self.logger.info(f"提取企业信息，共{len(pages_info)}条")
            peopele_info=await self.extract_people_info()
            self.logger.info(f"提取人员信息，共{len(peopele_info)}条")

            groups_info=await self.extract_groups_info()
            self.logger.info(f"提取群组信息，共{len(groups_info)}条")

            if mixed_results:
                finnal_results['people_or_company_info']=pages_info+peopele_info+mixed_results['profile_users']
                finnal_results['comment_people_info']=mixed_results['comment_users']
                finnal_results['groups_info']=groups_info

            self.logger.info(f"🕵️‍♂️ 采集facebook数据完成,提取人员信息，共{len(peopele_info)}条，提取企业信息，共{len(pages_info)}条，提取评论用户，共{len(mixed_results['profile_users'])}条", extra={"show_in_ui": 1, "task_id": self.task_id})
            
            
            return {'status':'success','step':{'profiles_found':len(finnal_results)},'results':finnal_results}
        
            
        except Exception as e:
            self.logger.error(f"搜索用户档案失败: {str(e)}")
            print(traceback.format_exc())
            return {'status':'success','step':{'profiles_found':len(finnal_results)},'results':finnal_results}
    
    async def extract_pages_info(self) -> list:
        """
        从Pages目录获取企业信息，提取页面和用户相关信息
        """
        results = []
        try:
            # 点击“Pages”标签，要求全匹配
            pages_tab = await self.page.query_selector('text="Pages"')
            if not pages_tab:
                self.logger.error("未找到Pages标签")
                return results
            await pages_tab.click()
            await asyncio.sleep(2)  
            # 同时等待"Follow"或"We didn't find any results"其一出现
          
            for _ in range(8):  
                if await self.page.query_selector('text="Follow"') or await self.page.query_selector('text="We didn\'t find any results"'):
                    break
                await asyncio.sleep(1)
                
           
            # 分页滚动抓取Pages信息
            seen_names = set()
            max_scroll_times = 1  # 最多滚动10次，防止死循环
            scroll_count = 0
            last_count = 0

            while scroll_count < max_scroll_times:
                # 获取搜索结果中的所有page item
                all_articles = await self.page.query_selector_all('div[aria-label="Search results"] div[role="article"]')
                # 只处理新出现的articles
                new_articles = all_articles[last_count:] if last_count < len(all_articles) else []
                self.logger.info(f"提取Pages信息，共{len(new_articles)}条新数据")
                if not new_articles:
                    # 没有新数据，或没有任何结果
                    if scroll_count == 0:
                        self.logger.info("未找到任何Pages搜索结果")
                    break
                last_count = len(new_articles)

                for item in new_articles:
                    info = {
                        "headline": "",   # user_info
                        "industry": "",   # category
                        "summary": "",    # page_info
                        "phone": "",
                        "website": "",
                        "address": "",
                        "name": "",
                        "email": ""
                    }
                    try:
                        # 1. 获取包含“·”的文本，分割类别和地址
                        dot_text_elem = await item.query_selector('xpath=.//*[contains(text(), "·")]')
                        if dot_text_elem:
                            dot_text = (await dot_text_elem.inner_text()).strip()
                            parts = [p.strip() for p in dot_text.split("·")]
                            if len(parts) >= 2:
                                info["industry"] = parts[0]   # category -> industry
                                # 排除包含followers的数据
                                lower_part = parts[1].lower()
                                if not any(x in lower_part for x in ["followers", "recommend", "reviews"]):
                                    info["address"] = parts[1]
                                else:
                                    continue  # 跳过包含followers的数据

                        # 2. 获取name字段
                        name_a = await item.query_selector('a[role="presentation"]')
                        if name_a:
                            name = await name_a.inner_text()
                            if name:
                                info["name"] = name

                        # 3. hover到企业头像，
                        profile_photo_a = await item.query_selector('a[aria-label^="Profile photo of "]')
                        if profile_photo_a:
                            href = await profile_photo_a.get_attribute("href")
                            if href:
                                info["profile_url"] = href
                            await profile_photo_a.hover()
                            await asyncio.sleep(3)
                            # 获取Link preview下的所有listitem
                            info=await self._extract_preview_info(info)
                            await dot_text_elem.hover()
                            await asyncio.sleep(1)

                        # 去重：以name为唯一标识
                        name_key = info.get("name", "")
                        if name_key and name_key not in seen_names:
                            results.append(info)
                            seen_names.add(name_key)
                    except Exception as e:
                        self.logger.warning(f"解析单个Page信息出错: {str(e)}")
                        continue

                # 页面滚动到底部，加载更多
                await self.page.evaluate("window.scrollBy(0, window.innerHeight);")
                await asyncio.sleep(2)
                scroll_count += 1

            # 优化：只获取一次db_session，批量处理所有profile
            async for db_session in db_manager.get_session():
                user_profile_repo = UserProfileRepository(db_session)
                for page_info in results:
                    profile = FaceBookProfile(**page_info, platform="Facebook")
                    try:
                        saved_profile = await user_profile_repo.create(profile.dict())
                    except Exception as e:
                        self.logger.warning(f"保存用户档案失败: {str(e)}")
                        await db_session.rollback()
                        continue
                break  # 处理完所有后退出
            return results
            
        except Exception as e:
            self.logger.error(f"提取Pages信息失败: {str(e)}")
            return results
    
    async def _extract_preview_info(self, info: dict,page=None) -> dict:
        if not page:
            page=self.page
        preview_listitems = await page.query_selector_all('div[aria-label="Link preview"] [role="listitem"]')
        if preview_listitems and len(preview_listitems) >= 2:
            # 第一个是Page信息
            info["summary"] = (await preview_listitems[0].inner_text()).strip()    # page_info -> summary
            # 第二个是用户信息
            info["headline"] = (await preview_listitems[1].inner_text()).strip()  # user_info -> headline
            # 第三个和第四个
            # 遍历所有preview_listitems，提取email、phone、website
            import re
            email_pattern = re.compile(r"[\w\.-]+@[\w\.-]+\.\w+")
            # 能提取+234 703 121 2338这种号码的正则
            phone_pattern = re.compile(r"(\+\d{1,4}[\s\-]?)?(\(?\d{2,4}\)?[\s\-]?)?(\d{3,4}[\s\-]?){2,3}\d{2,4}")
            url_pattern = re.compile(r"(https?://[^\s]+)")

            for idx, li in enumerate(preview_listitems[2:], start=2):
                text = (await li.inner_text()).strip()
                # 检查email
                email_match = email_pattern.search(text)
                if email_match:
                    info["email"] = email_match.group(0)
                    continue
                # 检查phone
                phone_match = phone_pattern.search(text)
                if phone_match:
                    # 统一去除首尾空格，确保phone为纯字符串
                    phone_value = phone_match.group(0).strip()
                    # 避免phone被json.dumps时加双引号，确保类型为str
                    info["phone"] = str(phone_value)
                    continue
                # 检查website
                url_match = url_pattern.search(text)
                if url_match:
                    info["website"] = url_match.group(0)
                    continue
                # 兜底：如果没有匹配，且内容像手机号
                if text.isdigit() and not info.get("phone"):
                    info["phone"] = str(text)
                elif not info.get("website") and ("www." in text or ".com" in text or ".cn" in text or ".net" in text):
                    info["website"] = text

        return info
                    
    async def extract_people_info(self) -> list:
        """
        从People目录获取人员信息，提取name、profile_url、avatar_url、summary等字段
        """
        results = []
        try:
            people_tab = await self.page.query_selector('text="People"')
            if not people_tab:
                self.logger.error("未找到People标签")
                return results
            await people_tab.click()
            await asyncio.sleep(2)
           
            for _ in range(8):  # 最多等待8秒，每秒检查一次
                if await self.page.query_selector('text="Add friend"') or await self.page.query_selector('text="We didn\'t find any results"'):
                    break
                await asyncio.sleep(1)
            max_scroll_times = 1  # 最多滚动10次，防止死循环
            scroll_count = 0
            last_count = 0

            while scroll_count < max_scroll_times:
                # 获取role="feed"下的人员列表元素
                people_feed = await self.page.query_selector('div[role="feed"]')
                if not people_feed:
                    self.logger.error("未找到People列表（role=feed）")
                    return results

                # 获取所有人员item，只处理新一轮加载出来的
                all_people_items = await people_feed.query_selector_all('div[role="article"]')
                # 只处理新加载的item
                new_people_items = all_people_items[last_count:] if last_count < len(all_people_items) else []
                self.logger.info(f"提取People信息，共{len(new_people_items)}条新数据")
                if not new_people_items:
                    self.logger.info("未找到任何People搜索结果")
                    return results
                last_count = len(all_people_items)

                for item in new_people_items:
                    info = {
                        "name": "",
                        "profile_url": "",
                        "avatar_url": "",
                        "summary": ""
                    }
                    try:
                        # 1. 获取name和profile_url
                        name_a = await item.query_selector('a[role="presentation"]')
                        if name_a:
                            name = await name_a.inner_text()
                            if name:
                                info["name"] = name
                            href = await name_a.get_attribute("href")
                            if href:
                                info["profile_url"] = href

                        # 2. 获取avatar_url
                        avatar_a = await item.query_selector('a[aria-label^="Profile photo of "]')
                        if avatar_a:
                            img = await avatar_a.query_selector('image,img')
                            if img:
                                avatar_url = await img.get_attribute("xlink:href") or await img.get_attribute("src")
                                if avatar_url:
                                    info["avatar_url"] = avatar_url

                        # 3. 获取summary（item的全部文本）
                        summary = (await item.inner_text()).strip()
                        info["summary"] = summary

                        results.append(info)
                    except Exception as e:
                        self.logger.warning(f"解析单个人员信息出错: {str(e)}")
                        continue
                # 页面滚动到底部，加载更多
                await self.page.evaluate("window.scrollBy(0, window.innerHeight);")
                await asyncio.sleep(2)
                scroll_count += 1
            for info in results:
                profile = FaceBookProfile(**info, platform="Facebook")
                async for db_session in db_manager.get_session():
                    user_profile_repo = UserProfileRepository(db_session)
                    saved_profile = await user_profile_repo.create(profile.dict())
                    break
            return results
         
        except Exception as e:
            self.logger.error(f"提取People信息失败: {str(e)}")
            return []

    async def extract_all_reels_and_story_comments(self) -> list:
        """
        点击文本为All的元素，然后调用extract_reels_and_comments和extract_story_comments方法
        """
        mixed_results ={'profile_users':[],'comment_users':[]}
        try:
            # 滚动10页，收集Reel和Story/Photo链接
            reel_links = set()
            story_links = set()
            page_count=10
            self.logger.info(f"开始提取Reel和Story/Photo链接，共{page_count}页")
            for _ in range(page_count):
                # 1. 获取所有视频帖子的链接（Reels）
                reel_items = await self.page.query_selector_all('[aria-label="Open reel in Reels Viewer"]')
                for item in reel_items:
                    try:
                        href = await item.get_attribute("href")
                        if href:
                            
                            reel_links.add('https://www.facebook.com'+href)
                    except Exception as e:
                        self.logger.warning(f"获取Reel链接失败: {str(e)}")
                        continue

                # 2. 通过 https://www.facebook.com/photo/ 获取所有帖子元素
                story_items = await self.page.query_selector_all('a[href^="https://www.facebook.com/photo/"]')
                for item in story_items:
                    try:
                        a_tags = [item]  # 直接将item作为a标签处理
                        for a in a_tags:
                            href = await a.get_attribute("href")
                            if href:
                                story_links.add(href)
                    except Exception as e:
                        self.logger.warning(f"获取Story/Photo链接失败: {str(e)}")
                        continue

                # 页面滚动到底部，加载更多内容
                await self.page.evaluate("window.scrollBy(0, window.innerHeight);")
                await asyncio.sleep(2)

            # 将reel_links和story_links合并并打乱顺序后传递给方法
            all_links = list(reel_links.union(story_links))
            self.logger.info(f"开始提取视频和图文的目标客户")
            if all_links:
                import random
                random.shuffle(all_links)
                mixed_results = await self.extract_reels_and_comments(all_links)
               

            return mixed_results


        except Exception as e:
            self.logger.error(f"提取All-Reels-Story评论失败: {str(e)}")
            return mixed_results
    async def extract_reels_and_comments(self, reel_links: list) -> list:
        """
        1. 点击文本为All的元素
        2. 获取aria-label="Open reel in Reels Viewer"的元素列表
        3. 遍历每个item，提取summary和评论数，若评论数>0则中键点击评论按钮，获取新页面评论信息
        """
        comment_users_and_profile_users={'profile_users':[],'comment_users':[]}
        results = []     
        profile_users=[]   
        try:
            new_page = await self.page.context.new_page()        
        except:
            pass
        try:
       
            for link in reel_links:
                self.logger.info(f"开始提取{link}的信息")
                # 新开一个page加载link
               
                await new_page.goto(link)
                await asyncio.sleep(2)
                await new_page.wait_for_load_state("domcontentloaded", timeout=10000)
                 # 点击评论按钮
                if 'reel' in link:
                    comment_btn = await new_page.query_selector('[aria-label="Comment"]')
                    if comment_btn:
                        await comment_btn.click()
                        await asyncio.sleep(1)
                                
                await new_page.wait_for_selector('[role="complementary"]', timeout=10000)
                item = await new_page.query_selector('[role="complementary"]')
                if item:
                    # 如果有See more文本的元素，点击它，等待See less出现，然后获取See less的父元素文本作为summary
                    see_more_elem = await item.query_selector('text="See more"')
                    summary = ""
                    self.logger.info(f"提取{link}的信息，summary: {summary}")
                    if see_more_elem:
                        try:     
                            await see_more_elem.click()
                            await asyncio.sleep(1)
                            # 等待See less元素出现
                            await new_page.wait_for_selector('text="See less"', timeout=3000)
                            see_less_elem = await item.query_selector('text="See less"')
                            if see_less_elem:
                                # 获取See less的父元素
                                parent_elem = await see_less_elem.evaluate_handle("el => el.parentElement")
                                if parent_elem:
                                    summary = await parent_elem.inner_text()
                                    summary = summary.strip() if summary else ""
                        except Exception as e:
                            self.logger.warning(f'处理See more/See less时出错: {str(e)}')
                    else:
                        summary_elems = await item.query_selector_all('[dir="auto"]')
                        summary = ""
                        if summary_elems:
                            # 合并所有summary_elems的文本作为summary
                            texts = []
                            for elem in summary_elems:
                                text = await elem.inner_text()
                                if text:
                                    texts.append(text.strip())
                            summary = "\n".join(texts)
                    
                    # 找到aria-label="See Owner Profile"的元素或者包含, view story的a标签，hover上去 获取a标签的href 作为href
                    info={}
                    href = ""
                    if 'reel' in link:
                        owner_profile_elems = await item.query_selector_all('a[aria-label="See Owner Profile"]')
                        if owner_profile_elems:
                            owner_profile_elem=owner_profile_elems[-1]
                            href = await owner_profile_elem.get_attribute("href")
                            info["name"] = await owner_profile_elem.inner_text()
                            await owner_profile_elem.hover()
                    else:
                        # 查找aria-label中包含", view story"的a标签
                        a_tags = await item.query_selector_all('a[aria-label*=", view story"]')
                        try:
                            if a_tags: 
                                a_tag=a_tags[-1]   
                                href = await a_tag.get_attribute("href")
                                aria_label = await a_tag.get_attribute("aria-label")
                                info["name"] = aria_label.replace(", view story", "").strip() if aria_label else ""
                                await a_tag.hover()
                            else:
                                name_tags = await item.query_selector_all('span[dir="auto"] a')
                                if name_tags:
                                    a_tag=name_tags[-1]
                                    href = await a_tag.get_attribute("href")
                                    info["name"] = a_tag.inner_text()
                                    await a_tag.hover()
                        except Exception as e:
                            pass
                    self.logger.info(f"提取{link}的信息，name: {info['name']}, profile_url: {href}")
                    if href and not href.startswith("http"):
                        href = "https://facebook.com" + href if not href.startswith("/") else "https://facebook.com" + href
                    else:
                        info["profile_url"] = href
                    info["summary"] = summary
                   
                  
                    info=await self._extract_preview_info(info)
                    self.logger.info(f"提取{link}卡片信息: {info}")
                    # hover div aria-label="Your profile"元素
                    try:
                        profile_div = await self.page.query_selector('div[aria-label="Your profile"]')
                        if profile_div:
                            await profile_div.hover()
                            await asyncio.sleep(1)  # 等待hover效果
                    except Exception as e:
                        self.logger.warning(f"hover Your profile元素失败: {str(e)}")
                        
                    if info.get("profile_url") :
                        profile_users.append(info)

                    comments = await self._extract_comments_from_new_page(new_page)
                    self.logger.info(f"提取{link}的评论信息，共{len(comments)}条")
                    for comment in comments:
                        results.append({
                            "platform":"Facebook",
                            "link": link,  # 帖子的链接
                            "summary":summary,  # 帖子的内容
                            "comment_name":comment.get("comment_name", ""),  # 评论人名字
                            "comment_profile_url":comment.get("comment_profile_url", ""),  # 评论人facebook主页链接
                            "comment_time":comment.get("comment_time", ""),  # 评论时间
                            "comment_text":comment.get ("comment_text", ""),  # 评论的内容
                        })
                    if results:
                        comment_users_and_profile_users['comment_users']=results
                        async for db_session in db_manager.get_session():
                            comment_repo = CommentRepository(db_session)
                            # 转为dict类型再批量插入
                            await comment_repo.create_many([dict(item) for item in results])
                            await db_session.commit()
                            break
                        
                    if profile_users:
                        comment_users_and_profile_users['profile_users']=profile_users
                        async for db_session in db_manager.get_session():
                            user_profile_repo = UserProfileRepository(db_session)
                          
                            try:
                                # 将字典转换为 FaceBookProfile 对象，然后转换为字典列表
                                profiles = [FaceBookProfile(**user_info, platform="Facebook") for user_info in profile_users]
                                saved_profile = await user_profile_repo.create_many([profile.dict() for profile in profiles])
                               
                            except Exception as e:
                                self.logger.warning(f"保存用户档案失败: {str(e)}")
                                await db_session.rollback()
                            break  
                        
            
        
        except Exception as e:
            import traceback
            self.logger.warning(f"解析Reel信息出错: {str(e)}\n{traceback.format_exc()}")
        finally:
            try:
                await new_page.close()
            except Exception as e:
                self.logger.warning(f"关闭新页面失败: {str(e)}")
        return comment_users_and_profile_users
        

    async def _extract_comments_from_new_page(self, page) -> list:
        """
        在新打开的页面中，点击评论按钮，等待评论列表出现，提取评论信息
        """
        comments = []
        try:
            # 点击评论按钮
            # 等待"No comments yet"文本元素或评论元素出现
            # 同时等待"无评论"或评论元素出现，或用js判断
            try:
                for index in range(10):
                    if await page.query_selector('[aria-label^="Comment by "]') or await page.query_selector('text="No comments yet"'):
                        break
                    await asyncio.sleep(1)
            except Exception:
                self.logger.warning("未检测到评论或'No comments yet'提示")
            comment_items = await page.query_selector_all('[aria-label^="Comment by "]')
            for item in comment_items:
                try:
                    # 获取profile_url
                    a_tag = await item.query_selector('a')
                    profile_url = await a_tag.get_attribute("href") if a_tag else ""
                    # 获取item文本
                    item_text = await item.inner_text()
                    # 尝试提取name和时间
                    name = ""
                    time_text = ""
                    if item_text:
                        lines = item_text.split("\n")
                        if len(lines) >= 1:
                            name = lines[0]
                            
                            # 查找时间文本 - 寻找符合时间格式的行
                            for line in lines:
                                line = line.strip()
                                # 匹配相对时间格式 (1d, 2h, 3m, 1y 等)
                                if re.match(r'^\d+[dhmy]$', line.lower()):
                                    time_text = line
                                    break
                          
                    # 处理时间文本，转换相对时间为绝对时间
                    processed_time = self.parse_time_text(time_text)
                    
                    comments.append({
                        "comment_profile_url": profile_url,
                        "comment_name": name,
                        "comment_text": item_text,
                        "comment_time": processed_time
                    })
                except Exception as e:
                    self.logger.warning(f"解析评论信息出错: {str(e)}")
                    continue
            return comments
        except Exception as e:
            self.logger.error(f"提取评论信息失败: {str(e)}")
            return []

    async def extract_story_comments(self, story_links: list) -> list:
        """
        获取所有story_message及其评论信息
        """
        results = []
        try:
            new_page = await self.page.context.new_page()
            for link in story_links:
                await self.page.goto(link)
                await asyncio.sleep(2)
                await self.page.wait_for_load_state("domcontentloaded", timeout=10000)
                item = await self.page.query_selector('[data-ad-rendering-role="story_message"]')
                if item:
                    try:
                        # 获取summary
                        summary_elem = await item.query_selector('[dir="auto"]')
                        summary = await summary_elem.inner_text() if summary_elem else ""
                        # 查找包含comments文本的元素
                        comment_btn = None
                        comment_number = 0
                        comment_elems = await item.query_selector_all('[dir="auto"]')
                        for elem in comment_elems:
                            text = await elem.inner_text()
                            if "comment" in text.lower():
                                # 提取数字
                                import re
                                match = re.search(r'(\d+)', text)
                                if match:
                                    num = int(match.group(1))
                                    if num > 0:
                                        comment_btn = elem
                                        comment_number = num
                                        break
                        comments = []
                        if comment_btn:
                            try:
                                await comment_btn.click()
                                await asyncio.sleep(1)
                                # 复用已有的评论提取逻辑
                                comments = await self._extract_comments_from_new_page(new_page)
                            except Exception as e:
                                self.logger.warning(f"点击评论按钮或提取评论失败: {str(e)}")
                        results.append({
                            "summary": summary,
                            "comments_count": comment_number,
                            "comments": comments
                        })
                    except Exception as e:
                        self.logger.warning(f"解析story_message及评论出错: {str(e)}")
                        continue
            return results
        except Exception as e:
            self.logger.error(f"提取story_message及评论信息失败: {str(e)}")
            return []


    
    async def into_groups(self,count) -> list:
        """
        从Pages目录获取企业信息，提取页面和用户相关信息
        """
        results = []
        try:
            # 点击“Pages”标签，要求全匹配
            pages_tab = await self.page.query_selector('text="Groups"')
            if not pages_tab:
                self.logger.error("未找到Groups标签")
                return results
            await pages_tab.click()
            await asyncio.sleep(2)  
        
          
            for _ in range(8):  
                if await self.page.query_selector('text="Join"') or await self.page.query_selector('text="We didn\'t find any results"'):
                    break
                await asyncio.sleep(1)
            
            await self.click_join_buttons_until_count(count)
                
        except TimeoutError:
                self.logger.error("在Pages目录下未找到Follow或We didn't find any results标签，超时")
                return results
            
    async def click_join_buttons_until_count(self, target_count: int):
        """
        点击"Join"按钮直到达到目标数量
        :param target_count: 目标点击数量
        """
        clicked_buttons = set()  # 用于跟踪已点击的按钮
        clicked_count = 0
        
        while clicked_count < target_count:
            # 获取当前页面所有的"Join"按钮
            join_buttons = await self.page.query_selector_all('text="Join"')
            
            if not join_buttons:
                self.logger.info("未找到更多'Join'按钮")
                break
                
            # 过滤掉已经点击过的按钮
            new_buttons = []
            for button in join_buttons:
                # 获取按钮的唯一标识（可以使用按钮的文本内容或者其他属性）
                button_text = await button.inner_text()
                button_handle = str(button)
                
                if button_handle not in clicked_buttons:
                    new_buttons.append((button, button_handle))
            
            if not new_buttons:
                self.logger.info("没有新的'Join'按钮可点击，尝试滚动页面")
                # 滚动页面以加载更多内容
                await self.page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
                await asyncio.sleep(2)  # 等待页面加载
                continue
                
            # 点击新发现的按钮
            for button, button_handle in new_buttons:
                if clicked_count >= target_count:
                    break
                    
                try:
                    await button.click()
                    clicked_buttons.add(button_handle)
                    clicked_count += 1
                    self.logger.info(f"成功点击第 {clicked_count} 个'Join'按钮")
                    await asyncio.sleep(1)  # 避免点击过快
                except Exception as e:
                    self.logger.warning(f"点击'Join'按钮时出错: {str(e)}")
                    continue
            
            # 如果还需要更多按钮，滚动页面加载更多
            if clicked_count < target_count:
                self.logger.info("滚动页面以加载更多'Join'按钮")
                await self.page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
                await asyncio.sleep(3)  # 等待页面加载更多内容
        
        self.logger.info(f"总共点击了 {clicked_count} 个'Join'按钮")
        return clicked_count

    
    async def view_groups_posts(self):
        """
        查看Groups目录下的所有帖子
        """
        try:
            # 首先从数据库获取未加入的群组（is_joined=0）
            unjoined_groups = []
            async for db_session in db_manager.get_session():
                from database.repositories import GroupInfoRepository
                group_repo = GroupInfoRepository(db_session)
                # 获取未加入的群组
                unjoined_groups = await group_repo.get_groups_by_filter(is_joined=0)
                break
            
            self.logger.info(f"从数据库找到 {len(unjoined_groups)} 个未加入的群组")
            
            # 循环访问每个未加入的群组
            for group in unjoined_groups:
                try:
                    results = []
                    group_url = group.group_url
                    if not group_url:
                        self.logger.warning(f"群组 {group.group_name} 的group_url为空")
                        continue
                    
                    self.logger.info(f"访问群组页面: {group_url} - {group.group_name}")
                    
                    # 访问群组页面
                    try:
                        try:
                            self.page.set_default_navigation_timeout(60000)  # 60秒
    
                            # 使用 wait_until 参数确保页面完全加载
                            await self.page.goto(group_url, wait_until= 'domcontentloaded',timeout=30000)
                                
                        except Exception as e:
                            self.logger.error(f"访问群组页面 {group_url} 时出错: {str(e)}")
                      
                        await self.page.wait_for_load_state("domcontentloaded")
                          # 等待一段时间再处理下一个群组
                        await asyncio.sleep(random.uniform(3, 6))
                    except Exception as e:
                        self.logger.error(f"访问群组页面 {group_url} 时出错: {str(e)}")
                      
                    
                    # 这里可以添加查看群组帖子的逻辑
                    # 例如：获取群组帖子、分析内容等
                    
                    # 模拟查看群组帖子的操作
                    self.logger.info(f"正在查看群组 {group.group_name} 的帖子")
                    
                  
                    
                    # 更新数据库，将is_joined字段设置为1
                    async for db_session in db_manager.get_session():
                        group_repo = GroupInfoRepository(db_session)
                        try:
                            await group_repo.update(group.id, {"is_joined": 1})
                            self.logger.info(f"已更新群组 {group.group_name} 的加入状态为已加入")
                        except Exception as e:
                            self.logger.error(f"更新群组加入状态失败: {str(e)}")
                            await db_session.rollback()
                        break
                    
                  
                     # 点击文本是"People"的tab
                    for _ in range(10):
                        people_tab=await self.page.query_selector_all('text="People"')
                        if people_tab[-1]:
                            is_visible = await people_tab[-1].is_visible()
                            is_enabled = await people_tab[-1].is_enabled()
                            if is_visible and is_enabled:
                                break
                        await asyncio.sleep(1)
                    people_tab = people_tab[-1]
                    if people_tab:
                        await people_tab.click()
                        self.logger.info("点击People标签后等待2秒")
                        await asyncio.sleep(2)
                        self.logger.info("点击People标签后等待2秒")
                        
                        
                        try:
                            await self.page.wait_for_selector('//*[@role="list"]/*[@role="listitem"]/div//a[@role="link" and @aria-label != ""]', timeout=10000)

                        except Exception as e:
                            pass
                        # 获取当前页面所有的//*[@role="list"]/*[@role="listitem"]/div//a[@role="link" and @aria-label !='']循环hover
                        self.logger.info("开始获取所有People链接")
                        people_links = await self.page.query_selector_all('//*[@role="list"]/*[@role="listitem"]/div//a[@role="link" and @aria-label != ""]')
                        for link in people_links:
                            try:
                                # hover链接
                                await link.hover()
                                await asyncio.sleep(5)
                                
                                # 声明info字典
                                info = {
                                    "headline": "",   # user_info 
                                    "industry": "",   # category 
                                    "summary": "",    # page_info 
                                    "phone": "", 
                                    "website": "", 
                                    "address": "", 
                                    "name": "", 
                                    "email": "" 
                                }
                                
                                # 调用_extract_preview_info提取信息
                                info = await self._extract_preview_info(info,self.page)
                                info["profile_url"] = 'https://www.facebook.com/' + await link.get_attribute('href') if await link.get_attribute('href') else ""
                                info['name'] = await link.get_attribute('aria-label') if await link.get_attribute('aria-label') else ""
                                # 添加到结果列表
                                self.logger.info(f"提取到的信息: {info}")
                                results.append(info)
                                try:
                                    profile_div = await self.page.query_selector('div[aria-label="Your profile"]')
                                    if profile_div:
                                        await profile_div.hover()
                                        await asyncio.sleep(1)  # 等待hover效果
                                except Exception as e:
                                    self.logger.warning(f"hover Your profile元素失败: {str(e)}")
                            except Exception as e:
                                self.logger.warning(f"处理人员链接时出错: {str(e)}")
                                continue
            
                    
                        
                        
                    
                        # 优化：只获取一次db_session，批量处理所有profile
                        async for db_session in db_manager.get_session():
                            user_profile_repo = UserProfileRepository(db_session)
                            for page_info in results:
                                profile = FaceBookProfile(**page_info, platform="Facebook")
                                try:
                                    saved_profile = await user_profile_repo.create(profile.dict())
                                except Exception as e:
                                    self.logger.warning(f"保存用户档案失败: {str(e)}")
                                    await db_session.rollback()
                                    continue
                            break  # 处理完所有后退出这个代码，保存到数据库
                            
                      
                except Exception as e:
                    self.logger.error(f"处理群组 {group.group_name if group else '未知'} 时出错: {str(e)}")
                    continue
           
        except Exception as e:
            import traceback
            print(traceback.format_exc())
            self.logger.error(f"查看Groups目录下的所有帖子失败: {str(e)}")
           
       

    async def send_message_to_profiles(self, message: str = "hello"):
        """
        从数据库user_profiles表中，根据account和platform字段获取数据，
        页面goto到profile_url链接，点击Add friend，然后点击Message发送消息
        
        Args:
            account (str): 账户名
            message (str): 要发送的消息，默认为"hello"
        """
        try:
            # 从数据库获取用户信息
            async for db_session in db_manager.get_session():
                user_profile_repo = UserProfileRepository(db_session)
                # 根据account和platform字段查询用户
                profiles = await  user_profile_repo.search(account_name=self.account, platform="Facebook",is_add_friend=0)
                break  # 处理完所有用户后退出

            if not profiles:
                self.logger.warning(f"未找到账户 {self.account} 的用户信息")
                return False
            
            self.logger.info(f"找到 {len(profiles)} 个用户配置文件")
            
            # 遍历所有找到的用户配置文件
            for profile in profiles:
                try:
                    profile_url = profile.profile_url
                    if not profile_url:
                        self.logger.warning(f"用户 {self.account} 的profile_url为空")
                        continue
                        
                    self.logger.info(f"访问用户资料页面: {profile_url}")
                    
                    # 访问用户资料页面
                    await self.page.goto(profile_url)
                    await self.page.wait_for_load_state("domcontentloaded")
                    await asyncio.sleep(3)
                    
                    # 点击"Add friend"按钮
                    if  await self._click_add_friend():
                         self.logger.info(f"用户 {self.account}--{profile.name}-{profile.profile_url}已添加为好友")
                         async for db_session in db_manager.get_session():
                            user_profile_repo = UserProfileRepository(db_session)
                            profiles = await  user_profile_repo.update(profile_id=profile.id, update_data={"is_add_friend": 1})
                            break  # 处理完所有用户后退出
                    message_btn = await self.page.wait_for_selector('text="Message"', timeout=10000)
                    if message_btn:
                        await message_btn.click()
                        self.logger.info("成功点击'Message'按钮")
                        await asyncio.sleep(2)
                            # 点击"Message"按钮并发送消息
                        is_send= await self._send_message(message)
                        self.logger.info(f"用户 {self.account}--{profile.name}-{profile.profile_url}已发送消息: {message}")
                        
                        self.logger.info(f"是否发送成功: {is_send} 发送消息: {message}")
                        username_element=await self.page.query_selector('//div[@aria-label="Chat settings"]//h2')
                        user_name=await username_element.text_content()
                        record={
                            'sender':self.account,
                            'content':message,
                            'receiver':user_name,
                            'is_send':1 if is_send else 0,
                        }
                        async for db_session in db_manager.get_session():
                            message_repository = MessageRepository(db_session)
                            try:
                                await message_repository.create(record)
                            except Exception as e:
                                self.logger.warning(f"保存用户档案失败: {str(e)}")
                                await db_session.rollback()
                                
                            break  # 处理完所有后退出
                        
                        # 等待一段时间再处理下一个聊天
                        await asyncio.sleep(1)
                    else:
                        self.logger.warning("未找到'Message'按钮")
                        
                    await asyncio.sleep(random.uniform(5, 10))
                    
                except Exception as e:
                    self.logger.error(f"处理用户 {self.account} 时出错: {str(e)}")
                    continue
                    
        
                
            return True
            
        except Exception as e:
            self.logger.error(f"发送消息给用户失败: {str(e)}")
            return False
    
    async def _click_add_friend(self):
        """
        点击"Add friend"按钮
        """
        try:
            # 等待并点击"Add friend"按钮
            button = await self.page.wait_for_selector('xpath=//*[text()="Add friend" or text()="View profile"]', timeout=10000)
            if button:
                add_friend_btn = await self.page.query_selector_all('text="Add friend"', timeout=10000)
                view_profile_btn = await self.page.wait_for_selector('text="View profile"', timeout=10000)
                if view_profile_btn:
                    return True
                if add_friend_btn:
                    await add_friend_btn.click()
                    self.logger.info("成功点击'Add friend'按钮")
                    await asyncio.sleep(2)
                    return True
                else:
                    self.logger.warning("未找到'Add friend'按钮")
        except Exception as e:
            self.logger.error(f"点击'Add friend'按钮时出错: {str(e)}")
        return False
    
    async def _send_message(self, message: str = "hello"):
        """
        点击"Message"按钮，等待消息输入框出现并发送消息
        
        Args:
            message (str): 要发送的消息
        """
        try:
            # 点击"Message"按钮
          
                
            # 等待消息输入框出现
            message_input = await self.page.wait_for_selector('[aria-label="Message"][data-lexical-editor]', timeout=20000)
            if message_input:
                # 在输入框中输入消息
                await message_input.fill(message)
                self.logger.info(f"成功输入消息: {message}")
                await asyncio.sleep(1)
                
                # 点击发送按钮
                send_btn = await self.page.wait_for_selector('[aria-label="Press enter to send"]', timeout=5000)
                if send_btn:
                    await send_btn.click()
                    self.logger.info("消息发送成功")
                else:
                    # 如果找不到发送按钮，尝试按回车键
                    await message_input.press("Enter")
                    self.logger.info("通过回车键发送消息成功")
                
                return True
            else:
                self.logger.warning("未找到消息输入框")
           
        except Exception as e:
            self.logger.error(f"发送消息时出错: {str(e)}")
        finally:
            close=await self.page.query_selector('[aria-label="Close chat"]')
            if close:
                await close.click()
                self.logger.info("成功关闭聊天窗口")
                
        return False
    

    async def extract_groups_info(self) -> list:
        """
        从Groups目录获取群组信息，提取组名、组链接、成员数、每日帖子量、是否已加入等信息
        """
        results = []
        try:
            # 点击"Groups"标签
            # 等待页面加载完成，检查"Join"或"We didn't find any results"
            for _ in range(8):
                if await self.page.query_selector('text="Recent Posts"'):
                    break
                await asyncio.sleep(1)

            groups_tab = await self.page.query_selector('text="Groups"')
            if not groups_tab:
                self.logger.error("未找到Groups标签")
                return results
            await groups_tab.click()
            await asyncio.sleep(2)
            
            # 等待页面加载完成，检查"Join"或"We didn't find any results"
            for _ in range(8):
                if await self.page.query_selector('text="Join"')   or await self.page.query_selector('text="We didn\'t find any results"'):
                    break
                await asyncio.sleep(1)
            
            # 获取所有的群组元素
            group_elements = await self.page.query_selector_all('//a[@role="presentation" and @tabindex="-1"]')
            self.logger.info(f"找到 {len(group_elements)} 个群组元素")
            group_other_info_elements=await self.page.query_selector_all('//span[contains(text(),"Public ·") and contains(text(),"K members · ")]')
            for index, group_element in enumerate(group_elements):
                try:
                    group_info = {
                        "group_name": "",
                        "group_url": "",
                        "member_count": 0,
                        "daily_post_count": 0,
                        "is_joined": 0  # 默认未加入
                    }
                    
                    # 获取组名
                   
                    group_info["group_name"] = await group_element.inner_text()
                    
                    # 获取组链接
                    href = await group_element.get_attribute("href")
                 
                    group_info["group_url"] = href
                    
                    # 检查是否已加入（检查是否有"Joined"文本）
               
                    # 查找包含成员数和帖子量的文本
                    info_texts =  group_other_info_elements[index]
                    text=await info_texts.inner_text()
                   # 提取成员数
                    if "members" in text:
                        # 提取数字
                        import re
                        member_match = re.search(r'Public · (\d+[KM]) members', text)
                        if member_match:
                            member_count_str = member_match.group(1).replace(',', '')
                            if 'k' in member_count_str.lower():
                                        member_count = float(member_count_str.lower().replace('k', '')) * 1000
                            elif 'm' in member_count_str.lower():
                                member_count = float(member_count_str.lower().replace('m', '')) * 1000000
                            else:
                                member_count = float(member_count_str)
                            group_info["member_count"] = int(member_count)
                         
                    
                    # 提取帖子量信息        
                    if "posts" in text:
                        # 尝试提取每日帖子量
                        daily_match = re.search(r' members · (\d+)\+ posts a day', text)
                        if daily_match:
                            group_info["daily_post_count"] = int(daily_match.group(1))
                
                    # 只有当有组名和组链接时才保存
                    if group_info["group_name"] and group_info["group_url"]:
                        results.append(group_info)
                        self.logger.info(f"提取群组信息: {group_info['group_name']} (已加入: {group_info['is_joined']})")

                except Exception as e:
                    self.logger.warning(f"解析单个群组信息出错: {str(e)}")
                    continue
            
            # 保存到数据库
            if results:

                async for db_session in db_manager.get_session():
                    group_repo = GroupInfoRepository(db_session)
                    try:
                        saved_groups = await group_repo.create_many(results)
                        self.logger.info(f"成功保存 {len(saved_groups)} 个群组信息到数据库")
                    except Exception as e:
                        self.logger.error(f"保存群组信息到数据库失败: {str(e)}")
                        await db_session.rollback()
                    break
            
            return results
            
        except Exception as e:
            self.logger.error(f"提取Groups信息失败: {str(e)}")
            return results

    
    
    async def run_task(self, task_id: str, **kwargs) -> Dict[str, Any]:
        """运行任务"""
        try:
            self.logger.info(f"开始执行任务: {task_id}")
            
            # 启动浏览器
            if not await self.start_browser():
                raise Exception("浏览器启动失败")
            
            # 检查登录状态
            if not await self.check_login_status():
                self.logger.info("未登录，开始登录流程")
                # 等待用户手动登录
                if not await self.login():
                    raise Exception("登录失败或超时")
            result=[]
            # 执行搜索任务
            search_params = FaceBookSearchParams(**kwargs)
            # result = await self.search_profiles(search_params)
            
            await self.view_groups_posts()
            # await self.send_message_to_profiles()
            # await self.send_messages_to_unread_chats()
            
            self.logger.info(f"任务完成: {task_id}")
            return result
            
        except Exception as e:
            self.logger.error(f"任务失败: {task_id}, 错误: {str(e)}")
            return {
                "task_id": task_id,
                "status": "failed",
                "step": {'error':str(e)},
            }
    
     
    async def run_chatting(self, task_id: str, **kwargs) -> Dict[str, Any]:
        """运行任务"""
        try:
            self.logger.info(f"开始执行任务: {task_id}")
            
            # 启动浏览器
            if not await self.start_browser():
                raise Exception("浏览器启动失败")
            
            # 检查登录状态
            if not await self.check_login_status():
                self.logger.info("未登录，开始登录流程")
                # 等待用户手动登录
                if not await self.login():
                    raise Exception("登录失败或超时")
         
            await self.send_messages_to_unread_chats()
            
            self.logger.info(f"任务完成: {task_id}")
        
            
        except Exception as e:
            self.logger.error(f"任务失败: {task_id}, 错误: {str(e)}")
            return {
                "task_id": task_id,
                "status": "failed",
                "step": {'error':str(e)},
            }

    async def send_messages_to_unread_chats(self, message: str = "hello"):
        """
        进入Facebook消息页面，点击"Unread"文本，获取聊天列表，并循环遍历发送消息
        
        Args:
            message (str): 要发送的消息，默认为"hello"
        
        """
        
        # 进入指定的Facebook消息页面
        message_url = "https://www.facebook.com/messages/"
        self.logger.info(f"正在访问消息页面: {message_url}")
        await self.page.goto(message_url)
        await asyncio.sleep(10)
        while True:
            try:
             
                try:
                    # 点击文本"Unread"
                    unread_elements = await self.page.query_selector_all('//div[@role="tab" and .//span[text()="Unread"]]')
                    if unread_elements:
                        is_selected = await unread_elements[-1].get_attribute('aria-selected')
                        if is_selected != 'true':
                            await unread_elements[-1].click()
                            self.logger.info("成功点击'Unread'文本")
                            await asyncio.sleep(2)
                    else:
                        self.logger.warning("未找到'Unread'文本")
                except Exception as e:
                    pass
                    
                # 获取聊天列表
                chat_links = await self.page.query_selector_all('//div[@aria-label="Chats"]//*[@role="gridcell"]//a[@role="link"]/div/div')
                self.logger.info(f"找到 {len(chat_links)} 个聊天链接")
                
                # 循环遍历聊天链接并发送消息
                for i, chat_link in enumerate(chat_links):
                    try:
                        self.logger.info(f"正在处理第 {i+1} 个聊天")
                        
                        # 点击聊天链接
                        await chat_link.click()
                        await asyncio.sleep(2)
                        element = await self.page.query_selector( '//div[contains(@aria-label,"Conversation with ")]')
                        aria_label = await element.get_attribute('aria-label')
                        user_name = aria_label.replace('Conversation with ', '')
                        self.logger.info(f"当前聊天用户: {user_name}")
                        new_chat_records=await self.process_chat_messages(user_name)
                        if new_chat_records:
                            # 发送消息
                            gen_message=await self.ai_gen_message(new_chat_records)
                            is_send=await self._send_message(gen_message)
                            self.logger.info(f"是否发送成功: {is_send} 发送消息: {gen_message}")
                            record={
                                'sender':self.account,
                                'content':gen_message,
                                'receiver':user_name,
                                'is_send':1 if is_send else 0,
                            }
                            async for db_session in db_manager.get_session():
                                message_repository = MessageRepository(db_session)
                                try:
                                    await message_repository.create(record)
                                except Exception as e:
                                    self.logger.warning(f"保存用户档案失败: {str(e)}")
                                    await db_session.rollback()
                                  
                                break  # 处理完所有后退出
                           
                            # 等待一段时间再处理下一个聊天
                            await asyncio.sleep(1)
                            

                    except Exception as e:
                        self.logger.error(f"处理第 {i+1} 个聊天时出错: {str(e)}")
                        continue
                        
                self.logger.info("所有未读聊天消息发送完成")
              
                
            except Exception as e:
                self.logger.error(f"发送未读聊天消息失败: {str(e)}")
                return False
            await asyncio.sleep(random.randint(30, 60))  
    
    async def ai_gen_message(self,message: str) -> str:
        """
        调用AI模型生成回复消息
        
        Args:
            message (str): 输入的消息
        
        Returns:
            str: 生成的回复消息
        """
        return 'hello'
    

    async def process_chat_messages(self,user_name):
        """
        根据指定的XPath元素获取所有聊天记录，判断消息发送者，并将消息内容保存到数据库
        
        Args:
            my_account_name (str): 当前账户名称，默认为"Me"
        """
        try:
            
          
            # 获取所有聊天记录元素
            chat_elements = await self.page.query_selector_all(
                '//div[contains(@aria-label,"Messages in conversation with")]//div[@data-scope="messages_table"]//span[contains(@style,"--x-fontSize: 15px;")]'
            )
            
            self.logger.info(f"找到 {len(chat_elements)} 条聊天记录")
            async def get_is_user_message(chat_elements) -> bool:
                """判断是否为用户发送的消息"""
                new_chat_records = []
                index = 0
                # 遍历每条聊天记录
                compare_label = await self.page.query_selector( f'//div[contains(@aria-label,"Conversation with ")]//span[text()="{user_name}"]')
                compare_label_box=await compare_label.bounding_box()
                compare_label_box_x = compare_label_box['x']
                for i, element in enumerate(chat_elements[::-1]):
                    # 获取元素的边界框信息
                    bounding_box = await element.bounding_box()
                    if not bounding_box:
                        self.logger.warning(f"无法获取第 {i+1} 条消息的边界框信息")
                        continue
                    
                    # 获取元素文本内容
                    message_content = await element.text_content()
                    if not message_content or not message_content.strip():
                        self.logger.warning(f"第 {i+1} 条消息内容为空")
                        continue
                    
                    # 获取span元素的宽度
                    span_width = bounding_box['width']
                    
                    # 获取元素左坐标
                    left_position = bounding_box['x']
                    
                    # 判断消息发送者
                    # 如果元素的左坐标小于span宽度的一半，认为是用户发送的消息
                    # 否则认为是自己账号发送的消息
                    if left_position < compare_label_box_x+5:
                        sender =user_name # 用户发送的消息
                        receiver = self.account  # 接收人是自己
                      
                    else:
                        sender = self.account  # 自己发送的消息
                        receiver = user_name  # 接收人是用户
                        break
                    # 保存聊天记录
                    new_chat_records.append({
                        "sender": sender,
                        "receiver": receiver,
                        "content": message_content.strip(),

                    })
                    
                return new_chat_records
                
            async def get_all_message(chat_elements) -> bool:
                """判断是否为用户发送的消息"""
                chat_records = []
                index = 0
                # 遍历每条聊天记录
                compare_label = await self.page.query_selector( f'//div[contains(@aria-label,"Conversation with ")]//span[text()="{user_name}"]')
                compare_label_box=await compare_label.bounding_box()
                compare_label_box_x = compare_label_box['x']
                for i, element in enumerate(chat_elements):
                    # 获取元素的边界框信息
                    bounding_box = await element.bounding_box()
                    if not bounding_box:
                        self.logger.warning(f"无法获取第 {i+1} 条消息的边界框信息")
                        continue
                    
                    # 获取元素文本内容
                    message_content = await element.text_content()
                    if not message_content or not message_content.strip():
                        self.logger.warning(f"第 {i+1} 条消息内容为空")
                        continue
                    
                    # 获取span元素的宽度
                    span_width = bounding_box['width']
                    
                    # 获取元素左坐标
                    left_position = bounding_box['x']
                    
                    # 判断消息发送者
                    # 如果元素的左坐标小于span宽度的一半，认为是用户发送的消息
                    # 否则认为是自己账号发送的消息
                    if left_position < compare_label_box_x+5:
                        sender =user_name # 用户发送的消息
                        receiver = self.account  # 接收人是自己
                      
                    else:
                        sender = self.account  # 自己发送的消息
                        receiver = user_name  # 接收人是用户
                        
                    # 保存聊天记录
                    chat_records.append({
                        "sender": sender,
                        "receiver": receiver,
                        "content": message_content.strip(),

                    })
                    
                return chat_records

            chat_records = await get_all_message(chat_elements)
            print(chat_records)
            return chat_records
                    
           
       
            
        except Exception as e:
            self.logger.error(f"处理聊天记录失败: {str(e)}")
            return False

    async def close(self):
        """关闭客户端"""
        await self.close_browser()